package com.example.commonmark.slice;

import com.example.commonmark.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import org.commonmark.Extension;
import org.commonmark.ext.autolink.AutolinkExtension;
import org.commonmark.ext.front.matter.YamlFrontMatterExtension;
import org.commonmark.ext.gfm.strikethrough.StrikethroughExtension;
import org.commonmark.ext.gfm.tables.TableBlock;
import org.commonmark.ext.gfm.tables.TablesExtension;
import org.commonmark.ext.heading.anchor.HeadingAnchorExtension;
import org.commonmark.ext.image.attributes.ImageAttributesExtension;
import org.commonmark.ext.ins.InsExtension;
import org.commonmark.ext.task.list.items.TaskListItemsExtension;
import org.commonmark.internal.util.Html5EntitiesUtil;
import org.commonmark.node.*;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.NodeRenderer;
import org.commonmark.renderer.html.*;
import org.commonmark.renderer.text.TextContentRenderer;

import java.util.*;

public class MainAbilitySlice extends AbilitySlice implements Component.ClickedListener {
    private ohos.agp.components.Text mTextMarkdown;
    private ohos.agp.components.Text mTextHtml;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);
        initView();
    }

    private void initView() {
        mTextMarkdown = ((ohos.agp.components.Text) findComponentById(ResourceTable.Id_text_markdown));
        mTextHtml = ((ohos.agp.components.Text) findComponentById(ResourceTable.Id_text_html));
        ((Button) findComponentById(ResourceTable.Id_parse_and_render_to_html)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_visitor_to_process_parsed_nodes)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_add_or_change_attributes)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_customize_html_rendering)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_autolink)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_strikethrough)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_tables)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_heading_anchor)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_ins)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_yaml_front_matter)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_image_attributes)).setClickedListener(this);
        ((Button) findComponentById(ResourceTable.Id_task_list_items)).setClickedListener(this);
    }

    @Override
    public void onClick(Component component) {
        String markdown = "";
        String html = "";
        Parser parser = null;
        Node document = null;
        HtmlRenderer renderer = null;
        Set<Extension> extensions = null;
        TextContentRenderer contentRenderer = null;

        switch (component.getId()) {
            case ResourceTable.Id_parse_and_render_to_html:
                parser = Parser.builder().build();
                markdown = "This is *Sparta*";
                document = parser.parse(markdown);
                renderer = HtmlRenderer.builder().build();
                html = renderer.render(document); // "<p>This is <em>Sparta</em></p>\n"
                break;
            case ResourceTable.Id_visitor_to_process_parsed_nodes:
                parser = Parser.builder().build();
                markdown = "Example\n=======\n\nSome more text";
                document = parser.parse(markdown);
                WordCountVisitor visitor = new WordCountVisitor();
                document.accept(visitor);
                html = "the result is a tree of nodes:" + visitor.wordCount;
                break;
            case ResourceTable.Id_add_or_change_attributes:
                parser = Parser.builder().build();
                renderer = HtmlRenderer.builder()
                        .attributeProviderFactory(new AttributeProviderFactory() {
                            public AttributeProvider create(AttributeProviderContext context) {
                                return new ImageAttributeProvider();
                            }
                        })
                        .build();

                markdown = "![text](/url.png)";
                document = parser.parse(markdown);
                html = renderer.render(document);// "<p><img src=\"/url.png\" alt=\"text\" class=\"border\" /></p>\n"
                break;
            case ResourceTable.Id_customize_html_rendering:
                parser = Parser.builder().build();
                renderer = HtmlRenderer.builder()
                        .nodeRendererFactory(new HtmlNodeRendererFactory() {
                            public NodeRenderer create(HtmlNodeRendererContext context) {
                                return new IndentedCodeBlockNodeRenderer(context);
                            }
                        })
                        .build();

                markdown = "Example:\n\n    code";
                document = parser.parse(markdown);
                html = renderer.render(document); // "<p>Example:</p>\n<pre>code\n</pre>\n"
                break;
            case ResourceTable.Id_autolink:
                extensions = Collections.singleton(AutolinkExtension.create());
                parser = Parser.builder().extensions(extensions).build();
                renderer = HtmlRenderer.builder().extensions(extensions).build();

                markdown = "http://example.com"/*"foo@example.com"*//*"www.example.com"*/;
                document = parser.parse(markdown);
                html = renderer.render(document);
                break;
            case ResourceTable.Id_strikethrough:
                extensions = Collections.singleton(StrikethroughExtension.create());
                parser = Parser.builder().extensions(extensions).build();
                renderer = HtmlRenderer.builder().extensions(extensions).build();
                contentRenderer = TextContentRenderer.builder()
                        .extensions(extensions).build();

                markdown = "~~you~~";
                document = parser.parse(markdown);
                html = renderer.render(document);
//                html = contentRenderer.render(document);
                break;
            case ResourceTable.Id_tables:
                markdown = "| hello | hi   | 哈哈哈   |\n" +
                "| ----- | ---- | ----- |\n" +
                "| 斯维尔多  | 士大夫  | f啊    |\n" +
                "| 阿什顿发  | 非固定杆 | 撒阿什顿发 |\n" +
                "\n";
//                markdown = "[imCoding 爱编程](http://www.lirenmi.cn)";
                html = markdownToHtmlExtensions(markdown);
                break;
            case ResourceTable.Id_heading_anchor:
                extensions = Collections.singleton(HeadingAnchorExtension.create());
                parser = Parser.builder().build();
                renderer = HtmlRenderer.builder().extensions(extensions).build();

                markdown = "[imCoding 爱编程](http://www.lirenmi.cn)";
                document = parser.parse(markdown);
                html = renderer.render(document);
                break;
            case ResourceTable.Id_ins:
                extensions = Collections.singleton(InsExtension.create());
                parser = Parser.builder().extensions(extensions).build();
                renderer = HtmlRenderer.builder().extensions(extensions).build();
                contentRenderer = TextContentRenderer.builder()
                        .extensions(extensions).build();

                markdown = "++you++";
                document = parser.parse(markdown);
                html = renderer.render(document);
//                html = contentRenderer.render(document);
                break;
            case ResourceTable.Id_yaml_front_matter:
                extensions = Collections.singleton(YamlFrontMatterExtension.create());
                parser = Parser.builder().extensions(extensions).build();
                renderer = HtmlRenderer.builder().extensions(extensions).build();

                markdown = "---\nFoo\n---\nBar\n---\nBaz\n";
                document = parser.parse(markdown);
                html = renderer.render(document);
                break;
            case ResourceTable.Id_image_attributes:
                extensions = Collections.singleton(ImageAttributesExtension.create());
                parser = Parser.builder().extensions(extensions).build();
                renderer = HtmlRenderer.builder().extensions(extensions).build();

                markdown = "![text](/url.png){width=640 height=480}";
                document = parser.parse(markdown);
                html = renderer.render(document);
                break;
            case ResourceTable.Id_task_list_items:
                extensions = Collections.singleton(TaskListItemsExtension.create());
                parser = Parser.builder().extensions(extensions).build();
                renderer = HtmlRenderer.builder().extensions(extensions).build();

                markdown = "- [ ] task #1\n" +
                        "- [x] task #2";
                document = parser.parse(markdown);
                html = renderer.render(document);
                break;
            default:
                break;
        }
        Html5EntitiesUtil.info(html);
        mTextMarkdown.setText(markdown);
        mTextHtml.setText(html);
    }

    class WordCountVisitor extends AbstractVisitor {
        int wordCount = 0;

        @Override
        public void visit(Text text) {
            // This is called for all Text nodes. Override other visit methods for other node types.

            // Count words (this is just an example, don't actually do it this way for various reasons).
            wordCount += text.getLiteral().split("\\W+").length;

            // Descend into children (could be omitted in this case because Text nodes don't have children).
            visitChildren(text);
        }
    }

    class ImageAttributeProvider implements AttributeProvider {
        @Override
        public void setAttributes(Node node, String tagName, Map<String, String> attributes) {
            if (node instanceof Image) {
                attributes.put("class", "border");
            }
        }
    }

    class IndentedCodeBlockNodeRenderer implements NodeRenderer {

        private final HtmlWriter html;

        IndentedCodeBlockNodeRenderer(HtmlNodeRendererContext context) {
            this.html = context.getWriter();
        }

        @Override
        public Set<Class<? extends Node>> getNodeTypes() {
            // Return the node types we want to use this renderer for.
            return Collections.<Class<? extends Node>>singleton(IndentedCodeBlock.class);
        }

        @Override
        public void render(Node node) {
            // We only handle one type as per getNodeTypes, so we can just cast it here.
            IndentedCodeBlock codeBlock = (IndentedCodeBlock) node;
            html.line();
            html.tag("pre");
            html.text(codeBlock.getLiteral());
            html.tag("/pre");
            html.line();
        }
    }


    /**
     * 增加扩展[标题锚点，表格生成] Markdown转换成HTML
     *
     * @param markdown md语法
     * @return String html语法
     */
    public static String markdownToHtmlExtensions(String markdown) {
        //h标题生成id
        Set<Extension> headingAnchorExtensions = Collections.singleton(HeadingAnchorExtension.create());
        //转换table的HTML
        List<Extension> tableExtension = Arrays.asList(TablesExtension.create());
        Parser parser = Parser.builder()
                .extensions(tableExtension)
                .build();
        Node document = parser.parse(markdown);
        HtmlRenderer renderer = HtmlRenderer.builder()
                .extensions(headingAnchorExtensions)
                .extensions(tableExtension)
                .attributeProviderFactory(new AttributeProviderFactory() {
                    public AttributeProvider create(AttributeProviderContext context) {
                        return new CustomAttributeProvider();
                    }
                })
                .build();
        return renderer.render(document);
    }

    /**
     * 处理标签的属性
     */
    static class CustomAttributeProvider implements AttributeProvider {
        @Override
        public void setAttributes(Node node, String tagName, Map<String, String> attributes) {
            //改变a标签的target属性为_blank
            if (node instanceof Link) {
                attributes.put("target", "_blank");
            }
            if (node instanceof TableBlock) {
                attributes.put("class", "ui celled table");
            }
        }
    }



    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }
}
